package gui.panels;

import geo.ani.CellAnisotropy;
import geo.ani.DottedAnisotropy;
import geo.ani.IAnisotropy;
import geo.ani.LinarAnisotropy;
import geo.math.GMath;
import geo.obj.Domain;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

import geo.obj.PhiObject;
import java.util.ArrayList;
import javax.swing.JPanel;

public class DomainDrawPanel extends JPanel{
	private Domain domain = new Domain(); 
	private static final long serialVersionUID = 1L;
	private int zoom = 1;
	private int ani = 10;
	private int step = 15;
	private int br = 20;
	private boolean _start = false;
	private int notset = 0;
	private ArrayList<PhiObject> pl = new ArrayList<PhiObject>(); 
	private Color anicolor = Color.LIGHT_GRAY;
	private Color bgcolor = Color.GRAY;
	private Color fgcolor = Color.WHITE;
	private Color axescolor = Color.BLACK;
	private double _dg = 0;
	private double _sn;
	
	public void setStep(int st){
		step = st;
	}
	
	public int getStep(){
		return step;
	}
	
	public void setDegree(double dg){
		_dg = dg;
	}
	
	public double getDegree(){
		return _dg;
	}
	
	public void setAxesColor(Color c){
		axescolor = c;
		repaint();
	}
	
	public void setFgColor(Color c){
		fgcolor = c;
		repaint();
	}
	
	public void setBgColor(Color c){
		bgcolor = c;
		repaint();
	}
	
	public void setAniColor(Color c){
		anicolor = c;
		repaint();
	}
	
	public void setParams(int stepo, int border, int height, int widht){
		step = stepo;
		br = border; 
		domain.setHeight(height);
		domain.setWidth(widht);
		repaint();
	}
	
	public DomainDrawPanel(){
		domain.setHeight(100);
		domain.setWidth(100);
		this.setPreferredSize(new Dimension(20, 20));
	}
	
	public void paint(Graphics g){
		
		initDraw(g);
		initAni(g);
		if(_start) initObj(g);
		initAxes(g);
	
	}
	
	private void initObj(Graphics g) {
		if(ani == 1){	//Dotted
			for(int i = 0; i < pl.size(); i++){
				if(pl.get(i).isWork()){
					g.setColor(pl.get(i).getColor());
					g.drawPolygon(pl.get(i).poly());
				}
			}
			g.setColor(Color.RED);
			for(int i = 0; i < pl.size(); i++){
				if(pl.get(i).isWork()){
					int[] xg = {(int)pl.get(i).getPx() - 1, (int)pl.get(i).getPx() + 1, (int)pl.get(i).getPx() + 1, (int)pl.get(i).getPx() - 1};
					int[] yg = {(int)pl.get(i).getPy() + 1, (int)pl.get(i).getPy() + 1, (int)pl.get(i).getPy() - 1, (int)pl.get(i).getPy() - 1};
					g.drawPolygon(xg, yg, 4);
				}
			}
			
			g.setColor(Color.BLACK);
		}
		else if(ani == 0){	//Cell
			
			for(int i = 0; i < pl.size(); i++){
				if(pl.get(i).isWork()){
					g.setColor(pl.get(i).getColor());
					g.drawPolygon(pl.get(i).poly());
				}
			}
			g.setColor(Color.RED);
			for(int i = 0; i < pl.size(); i++){
				if(pl.get(i).isWork()){
					int[] xg = {(int)pl.get(i).getPx() - 1, (int)pl.get(i).getPx() + 1, (int)pl.get(i).getPx() + 1, (int)pl.get(i).getPx() - 1};
					int[] yg = {(int)pl.get(i).getPy() + 1, (int)pl.get(i).getPy() + 1, (int)pl.get(i).getPy() - 1, (int)pl.get(i).getPy() - 1};
					g.drawPolygon(xg, yg, 4);
				}
			}
			
			g.setColor(Color.BLACK);
		}
		else if(ani == 2){	//Linar
			
			for(int i = 0; i < pl.size(); i++){
				if(pl.get(i).isWork()){
					g.setColor(pl.get(i).getColor());
					g.drawPolygon(pl.get(i).poly());
				}
			}
			g.setColor(Color.RED);
			for(int i = 0; i < pl.size(); i++){
				if(pl.get(i).isWork()){
					int[] xg = {(int)pl.get(i).getPx() - 1, (int)pl.get(i).getPx() + 1, (int)pl.get(i).getPx() + 1, (int)pl.get(i).getPx() - 1};
					int[] yg = {(int)pl.get(i).getPy() + 1, (int)pl.get(i).getPy() + 1, (int)pl.get(i).getPy() - 1, (int)pl.get(i).getPy() - 1};
					g.drawPolygon(xg, yg, 4);
				}
			}
			
			g.setColor(Color.BLACK);
			
		}
		else System.err.println("ERROR: No anisonropy selected!");
		
	}

	private void initAxes(Graphics g) {
		g.setColor(axescolor);
		g.drawLine(br * zoom, br * zoom, 200 * zoom, br * zoom);
		g.drawLine(br * zoom, br * zoom, br * zoom, 200 * zoom);
		g.drawString("x", 200 * zoom, (br-8) * zoom);
		g.drawString("y", (br-11) * zoom, 200 * zoom);
		g.drawString("0", (br-4) * zoom, (br-4) * zoom);
		g.drawLine(200 * zoom, br * zoom, 193 * zoom, (br-2) * zoom);
		g.drawLine(200 * zoom, br * zoom, 193 * zoom, (br+2) * zoom);
		g.drawLine(br * zoom, 200 * zoom, (br-2) * zoom, 193 * zoom);
		g.drawLine(br * zoom, 200 * zoom, (br+2) * zoom, 193 * zoom);
		
	}

	private void initAni(Graphics g) {
		if(ani == 1){	//Dotted anisotropy draw
			g.setColor(anicolor);
			for(int i = 0, l = (br+step) * zoom; i <= ((domain.getHeight() / step) * zoom); i++, l+=(step*zoom)){
				for (int j = 0, m = (br+step)*zoom; j <= ((domain.getWidth()*zoom)/ (step * zoom)); j++, m+=(step*zoom)){
					int x[] = {m - 1, m + 1, m + 1, m - 1};
					int y[] = {l + 1, l + 1, l - 1, l - 1};
					g.fillPolygon(x, y, 4);
				}
			}
		}
		
		else if(ani == 0){	//Cell anisotropy draw
			
			
			
			
			
			
			
			
			
			
			
			
			
			
			
			
			g.setColor(anicolor);
			int frststep = (br+step);
			int limit = (domain.getHeight()) / step;
			
			
			for(int i = 0, l = frststep; i <= limit; i++, l+=(step)){	
				g.drawLine(br, l, (domain.getWidth() + br+br), l);
			}
			
			
			for(int i = 0, l = (br+step) * zoom; i <= ((domain.getWidth()*zoom) / (step * zoom)); i++, l+=(step*zoom)){
				
				g.drawLine(l, br*zoom,l , (domain.getHeight() + br+br)*zoom);
			}

			
			
			
			
			
			
			
			
			
			
		}
		else if(ani == 2){	//Linar anisotropy draw
			
			int xcent = getWidth() / 2;
			int ycent = getHeight() / 2;
			int xend = getWidth() / 2;
			int yend = 100;
			double  c[] = GMath.rotate(xend - xcent, yend - ycent, _dg);
			 xend = (int) c[0] + xcent;
			 yend = (int) c[1] + ycent;
			g.drawLine(xcent, ycent, xend, yend);
			
			
			int x1x[] = new int[4];
			int y1y[] = new int[4];
			
			x1x[0] = xend - 3;
			y1y[0] = yend - 3;
			
			x1x[1] = xend + 3;
			y1y[1] = yend - 3;
			
			x1x[2] = xend + 3;
			y1y[2] = yend + 2;
			
			x1x[3] = xend - 3;
			y1y[3] = yend + 3;
			
			g.drawPolygon(x1x, y1y, 4);
			
			int x2x[] = {xcent - 2, xcent + 2, xcent + 2, xcent - 2};
			int y2y[] = {ycent - 2, ycent - 2, ycent + 2, ycent + 2};
			g.fillPolygon(x2x, y2y, 4);
			
		}
		
		g.setColor(Color.BLACK);
	}

	private void initDraw(Graphics g){
		g.setColor(bgcolor);
		g.fillRect(0, 0, getWidth(), getHeight());
		g.setColor(fgcolor);
		g.fillRect(br * zoom, br * zoom, (domain.getWidth() + br) * zoom, (domain.getHeight() + br) * zoom);
		g.setColor(Color.BLACK);

	}
	
	public void zoomIn(){
		zoom *= 2;
		setPreferredSize(new Dimension(domain.getWidth() * zoom, domain.getHeight() * zoom));
		repaint();
	}
	
	public void zoomOut(){
		if(zoom != 1){
			zoom /= 2;
			setPreferredSize(new Dimension(domain.getWidth() * zoom, domain.getHeight() * zoom));
			repaint();
		}
	}
	
	public void zoomFit(){
		zoom = 1;
		setPreferredSize(new Dimension(domain.getWidth() * zoom, domain.getHeight() * zoom));
		repaint();
	}
	
	public void run(int an, ArrayList<PhiObject> lol){
		
		ani = an;
		pl = lol;
		_start = true;
		IAnisotropy a = new DottedAnisotropy();
		
		switch(an){
		case 0 : a = new CellAnisotropy(); break;
		case 1 : a = new DottedAnisotropy(); break;
		case 2 : a = new LinarAnisotropy(); break;
		default : new DottedAnisotropy(); break;
		}
		
		if (an == 2){
			a.setDegree(_dg - _sn);
			a.culc(pl, 1, br, domain, this);
			_sn = _dg; //zero
			a.setDegree(0);
		}
		else
		{
			_dg = 0;
			a.setDegree(_dg - _sn);
			a.culc(pl, step, br, domain, this);
			_sn = 0;
		}
		repaint();
	}
	
	public int space(){
		double sum_obj = 0;
		for (int i = 0; i < pl.size(); i++){
			if(pl.get(i).isWork()){
				sum_obj += pl.get(i).culcSpace();
			}
		}
		double sum_d = domain.culcSpace();
		double pr = sum_obj/sum_d;
		double prs = pr * 100;
		return (int)prs;
	}
	
	public void addnotset(int ny){
		notset = ny;
	}
	
	public String report(){
		int cnt = 0;
		String npl = " object(s) not placede in domain:\n";
		for(int i = 0; i < pl.size(); i++){
			if(!pl.get(i).isWork()){
				cnt++;
				npl += pl.get(i).getName() + "\n";
			}
		}
		
		if(cnt == 0) return "All objects placed in domain.\nUsed " + space() + "% of domain space.\n";
		return cnt + npl + "Used " + space() + "% of domain space.\n";
	}
	
}